home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <limits.h>
- #include <sys/stat.h>
- #include "mailconf.h"
- #include "internal.h"
- #include "../misc/misc.h"
- #include "../dialog/dialog.h"
- #include "../userconf/userconf.h"
- #include "../netconf/netconf.h"
- #include "../paths.h"
- #include "mailconf.m"
-
- static MAILCONF_HELP_FILE help_aliases("aliases");
-
- static CONFIG_FILE f_aliases (ETC_ALIASES,help_aliases
- ,CONFIGF_MANAGED|CONFIGF_OPTIONNAL);
-
-
- class ALIAS: public ARRAY_OBJ{
- SSTRING name;
- SSTRINGS values;
- SSTRING comment;
- SSTRING filter;
- SSTRING file;
- /*~PROTOBEG~ ALIAS */
- public:
- ALIAS (char *line);
- ALIAS (void);
- private:
- void addoneval (const char *val);
- public:
- int edit (void);
- int file_ok (void);
- int filter_ok (void);
- const char *getname (void);
- int is_valid (void);
- private:
- void splitline (char *ptpt);
- public:
- void write (FILE *fout);
- /*~PROTOEND~ ALIAS */
- };
-
-
- PUBLIC ALIAS::ALIAS()
- {
- }
-
- static char *str_copyupto (char *dest, const char *src, char stop)
- {
- while (isgraph(*src) && *src != stop) *dest++ = *src++;
- *dest = '\0';
- return ((char*) src);
- }
-
- /*
- Add one element of the alias list
- */
- PRIVATE void ALIAS::addoneval(const char *val)
- {
- char *pt = str_skip (val);
- if (pt[0] == '|'){
- pt++;
- filter.setfrom (str_skip(pt));
- }else if (strncmp(val,":include:",9)==0){
- file.setfrom(val+9);
- }else{
- values.add (new SSTRING(val));
- }
- }
-
- /*
- Parse an alias list
- */
- PRIVATE void ALIAS::splitline(char *ptpt)
- {
- /* #Specification: mailconf / alias / limits
- We assume that an alias list has at most
- one command redirection and one include file.
- It may have as many other element (email address)
- as needed.
- */
- while (1){
- ptpt = str_skip (ptpt);
- if (ptpt[0] == '\0'){
- break;
- }else if (ptpt[0] == ','){
- ptpt++;
- }else if (ptpt[0] == '"'){
- char word[200];
- ptpt++;
- char *ptw = word;
- while (*ptpt != '\0' && *ptpt != '"') *ptw++ = *ptpt++;
- *ptw = '\0';
- if (*ptpt == '"') ptpt++;
- addoneval (word);
- }else{
- char word[200];
- ptpt = str_copyupto (word,ptpt,',');
- addoneval(word);
- }
- }
- }
-
- /*
- Used when reading the /etc/aliases file
-
- line will be trashed.
- */
- PUBLIC ALIAS::ALIAS(char *line)
- {
- char *pt = str_skip(line);
- if (pt[0] == '#'){
- comment.setfrom (pt);
- }else{
- char *ptpt = strchr(pt,':');
- if (ptpt != NULL){
- *ptpt++ = '\0';
- strip_end (pt);
- name.setfrom (pt);
- splitline (ptpt);
- }
- }
- }
-
- PUBLIC const char *ALIAS::getname()
- {
- return name.get();
- }
-
- PUBLIC int ALIAS::filter_ok()
- {
- if (!filter.is_empty()){
- /* #Specification: mailconf / aliases / filter program
- Linuxconf assumes the first word of the filter part of an
- alias is the program name (with or without path). It will
- check if the path exist either as is, or in /bin or /usr/bin.
-
- It will send a warning if the program can't be found.
- Complex script can be entered here and linuxconf may be
- fooled by this. It will just print a warning anyway
- and the alias will be accepted.
-
- If the program can be located, linuxconf will check that
- it is indeed executable.
- */
- char prog[PATH_MAX],binprog[PATH_MAX],usrbinprog[PATH_MAX];
- str_copyword(prog,filter.get());
- sprintf (binprog,"/bin/%s",prog);
- sprintf (usrbinprog,"/usr/bin/%s",prog);
- struct stat st;
- if (stat (prog,&st) == -1
- && stat (binprog,&st) == -1
- && stat (usrbinprog,&st) == -1){
- xconf_notice (MSG_U(N_MISSING,"%s does not exist"),prog);
- }else if ((st.st_mode & 0111)==0){
- xconf_notice (MSG_U(N_NOEXEC,"%s is not executable"));
- }
- }
- return 1;
- }
- PUBLIC int ALIAS::file_ok()
- {
- /* #Specification: mailconf / aliases / in a file
- When the user specify the indirect file for aliases
- mailconf check if the file exist and send a notice
- to the user if this is not the case. The
- operation is accepted anyway.
- */
- if (!file.is_empty()){
- if (!file_exist(file.get())){
- xconf_notice (MSG_R(N_MISSING),file.get());
- }
- }
- return 1;
- }
-
- /*
- Write one record
- */
- PUBLIC void ALIAS::write (FILE *fout)
- {
- if (!name.is_empty()){
- fprintf (fout,"%s: ",name.get());
- char *comma = " ";
- if (!filter.is_empty()){
- fprintf (fout,"\"| %s\" ",filter.get());
- comma = ",";
- }
- if (!file.is_empty()){
- fprintf (fout,"%s:include:%s ",comma,file.get());
- comma = ",";
- }
- int nb = values.getnb();
- for (int i=0; i<nb; i++){
- SSTRING *s = values.getitem(i);
- if (!s->is_empty()){
- fprintf (fout,"%s%s ",comma,s->get());
- if (i > 0 && i % 4 == 0){
- fputc ('\n',fout);
- comma = "\t,";
- }else{
- comma = ",";
- }
- }
- }
- }
- fprintf (fout,"%s\n",comment.get());
- }
- /*
- Is it a valid record or a comment
- */
- PUBLIC int ALIAS::is_valid()
- {
- return !name.is_empty();
- }
-
- /*
- Edit an alias definition.
- Return -1 if the user abort the edition (The record is left
- unchanged then).
- Return 0 if the user accepted the changes
- Return 1 if the user request the deletion of this record
- */
- PUBLIC int ALIAS::edit()
- {
- DIALOG dia;
- dia.newf_str (MSG_U(F_ALIASNAME,"alias name"),name);
- dia.newf_str (MSG_U(F_FILTER,"Filter program"),filter);
- dia.newf_str (MSG_U(F_LISTFILE,"List file"),file);
- /* #Specification: mailconf / aliases / limitation
- The user interface present minimally 10 lines
- for defining one alias value. A button ADD allows
- the user to get more lines.
- */
- dia.newf_title ("","");
- int i;
- for (i=values.getnb(); i<10; i++) values.add (new SSTRING);
- int vnb = values.getnb();
- for (i=0; i<vnb; i++){
- dia.newf_str ("",*values.getitem(i));
- }
- int no = 0;
- int ret = -1;
- while (1){
- MENU_STATUS code = dia.edit (
- MSG_U(T_ONEALIAS,"One alias definition")
- ,MSG_U(I_ONEALIAS
- ,"Use the button ADD to get more space\n"
- "in case you are defining a mailing list\n")
- ,help_aliases.getpath()
- ,no
- ,MENUBUT_ACCEPT|MENUBUT_CANCEL|MENUBUT_ADD|MENUBUT_DEL);
- if (code == MENU_ESCAPE || code == MENU_CANCEL){
- break;
- }else if (code == MENU_DEL){
- if (xconf_areyousure(MSG_U(Q_DELENTRY
- ,"Confirm deletion of this entry"))){
- ret = 1;
- break;
- }
- }else if (code == MENU_ADD){
- int curnb = values.getnb();
- for (i=0; i<10; i++) values.add (new SSTRING);
- vnb = values.getnb();
- for (i=curnb; i<vnb; i++){
- dia.newf_str ("",*values.getitem(i));
- }
- }else if (code == MENU_ACCEPT
- && perm_rootaccess(MSG_U(P_EDITALIAS,"edit an alias"))){
- if (name.is_empty()){
- no = 0;
- xconf_error (MSG_U(E_NONAME,"You must provide a name"));
- }else if (!filter_ok()){
- no = 1;
- }else if (!file_ok()){
- no = 1;
- }else if (!filter.is_empty()
- || !file.is_empty()){
- ret = 0;
- break;
- }else{
- for (i=0; i<vnb; i++){
- if (!values.getitem(i)->is_empty()){
- break;
- }
- }
- if (i == vnb){
- xconf_error (MSG_U(E_ALLEMPTY,"All values are empty"));
- no = 4;
- }else{
- ret = 0;
- break;
- }
- }
- }
- }
- if (ret == 0){
- setmodified();
- }else{
- dia.restore();
- }
- return ret;
- }
-
-
- class ALIASES: public ARRAY{
- /*~PROTOBEG~ ALIASES */
- public:
- ALIASES (void);
- private:
- void addline (char *buf);
- public:
- void addnew (void);
- private:
- int collect (const char **tb);
- public:
- void edit (void);
- ALIAS *getitem (int no);
- int locate (const char *name);
- void write (void);
- /*~PROTOEND~ ALIASES */
- };
-
- PUBLIC ALIAS *ALIASES::getitem(int no)
- {
- return (ALIAS*)ARRAY::getitem(no);
- }
-
- PRIVATE void ALIASES::addline (char *buf)
- {
- if (buf[0] != '\0') add (new ALIAS(buf));
- buf[0] = '\0';
- }
-
- PUBLIC ALIASES::ALIASES()
- {
- FILE *fin = f_aliases.fopen ("r");
- if (fin != NULL){
- char buf[10000];
- char line[1000];
- buf[0] = '\0';
- while (fgets(line,sizeof(line)-1,fin)!=NULL){
- strip_end (line);
- if (line[0] == '\0'){
- addline (buf);
- }else if (isspace(line[0])){
- strcat (buf,line);
- }else{
- addline (buf);
- strcpy (buf,line);
- }
- }
- addline(buf);
- rstmodified();
- }
- }
-
-
- /*
- Write back /etc/aliases
- */
- PUBLIC void ALIASES::write ()
- {
- FILE *fout = f_aliases.fopen ("w");
- if (fout != NULL){
- for (int i=0; i<getnb(); i++){
- getitem(i)->write(fout);
- }
- fclose (fout);
- rstmodified();
- /* #Specification: mailconf / aliases / updating
- Whenever the /etc/aliases is updated,
- the command "/usr/lib/sendmail -bi"
- is executed.
- */
- DAEMON *dae = daemon_find ("sendmail");
- if (dae->is_managed()){
- char cmd[200];
- sprintf (cmd,"%s -bi",dae->getpath());
- netconf_system (cmd);
- }
- }
- }
-
- /*
- Find an alias in the table.
- Return -1 if not found.
- Return the index otherwise.
- */
- PUBLIC int ALIASES::locate (const char *name)
- {
- int ret = -1;
- int nb = getnb();
- for (int i=0; i<nb; i++){
- /* #Specification: mailconf / user aliases / case sensitivity
- Email aliases are case insensitive and linuxconf properly
- check for a duplicate using stricmp().
- */
- if (stricmp(getitem(i)->getname(),name)==0){
- ret = i;
- break;
- }
- }
- return ret;
- }
-
- /*
- Add a new record
- */
- PUBLIC void ALIASES::addnew()
- {
- ALIAS *a = new ALIAS;
- while (a->edit()==0){
- if (locate(a->getname())!=-1){
- xconf_error (MSG_U(E_DUPALIAS,"Duplicate alias, rejected"));
- }else{
- add (a);
- write();
- a = NULL;
- break;
- }
- }
- delete a;
- }
-
- /*
- Build the menuopt table for xconf_menu.
- Return the number of line written.
-
- if tb is NULL, just count the number of line.
- tb will be sorted.
- */
- PRIVATE int ALIASES::collect(const char **tb)
- {
- int count = 0;
- int ii=0;
- for (int i=0; i<nb; i++){
- ALIAS *a = getitem(i);
- if (a->is_valid()){
- count++;
- if (tb != NULL){
- tb[ii++] = " ";
- tb[ii++] = a->getname();
- }
- }
- }
- if (tb != NULL){
- tb[ii] = NULL;
- menuopt_sort (tb,count,1);
- }
- return count;
- }
-
- /*
- Edit, add, delete record in the /etc/aliases file
- */
-
- PUBLIC void ALIASES::edit()
- {
- int choice = 0;
- while (1){
- int nb = collect(NULL);
- const char **menuopt
- = (const char**)malloc(((nb*2)+1)*sizeof(char*));
- collect(menuopt);
- MENU_STATUS code = xconf_menu(
- MSG_U(T_EDITALIASES,"Edit global mail aliases")
- ,MSG_U(IEDITALIASES
- ,"You are allowed to edit/add/deleted\n"
- "system wide aliases for electronic mail")
- ,help_aliases
- ,NULL
- ,NULL
- ,NULL
- ,MSG_U(I_NEWALIAS,"new aliases")
- ,menuopt
- ,choice);
- ALIAS *item = NULL;
- if (choice >=0 && choice < nb){
- item = getitem(locate(menuopt[choice*2+1]));
- }
- free ((char**)menuopt);
- if (code == MENU_ESCAPE || code == MENU_QUIT){
- break;
- }else if (code == MENU_OK){
- if (item != NULL){
- int ok = item->edit();
- if (ok != -1){
- if (ok == 1) remove_del (item);
- write();
- }
- }
- }else if (perm_rootaccess(MSG_U(P_WRITE,"write %s"),f_aliases.getpath())){
- if (code == MENU_ADD){
- addnew();
- }
- }
- }
- }
-
- void aliases_edit()
- {
- ALIASES al;
- al.edit();
- }
-
-